from typing import Optional, List
from typing import TypeVar, Generic
from pydantic import BaseModel
from pydantic.generics import GenericModel
from tortoise import Tortoise
from tortoise.contrib.pydantic import pydantic_model_creator

from models import User, Role, Menu, Dict

DataT = TypeVar('DataT')


class UserLogin(BaseModel):
    username: str
    password: str


class Response(GenericModel, Generic[DataT]):
    code: int = 0
    msg: str = 'ok'
    data: Optional[DataT]


class Token(BaseModel):
    id: int
    token: str


class BasicQuery(BaseModel):
    limit: int = 10
    page: int = 1


Tortoise.init_models(["models"], "models")

UserOut = pydantic_model_creator(User, name="User", exclude=('password',))
UserInBasic = pydantic_model_creator(User, name="UserIn", exclude_readonly=True)


class UserIn(UserInBasic):
    roles: List[int]


class UserQuery(BasicQuery):
    username: str = None


RoleOut = pydantic_model_creator(Role, name="Role", exclude=("users", "menus"))
RoleBasic = pydantic_model_creator(Role, name="RoleIn", exclude_readonly=True)


class RoleIn(RoleBasic):
    menus: List[int]


class RoleQuery(BasicQuery):
    name: str = None


MenuOut = pydantic_model_creator(Menu, name="Menu", exclude=('roles',))
MenuBasic = pydantic_model_creator(Menu, name="MenuIn", exclude_readonly=True)


class MenuIn(MenuBasic):
    meta: dict = None


DictOut = pydantic_model_creator(Dict, name="Dict")
DictBasic = pydantic_model_creator(Dict, name="DictIn", exclude_readonly=True)


class DictIn(DictBasic):
    value: dict = None
